//
// Created by Ivor_ on 2022/1/22.
//

#ifndef PHYSICAL_COMPUTING_PACKAGE_MATRIXOPERATE_H
#define PHYSICAL_COMPUTING_PACKAGE_MATRIXOPERATE_H

#include <string.h>
#include <math.h>
#include <complex.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include "matrixCalculate.h"

#define SHAPE_SQUARE 1
#define SHAPE_RECTANGLE 0
#define FORM_XY 1
#define FORM_RT 0

void prtCXY(_Complex double z0, double format);
void prtCRT(_Complex double z0, double format);
void fprtCXY(FILE* fp, _Complex double z0, double format);
void fprtCRT(FILE* fp, _Complex double z0, double format);

int* simDim(int, ...);
double* simDVec(int, ...);
_Complex double* simCVec(int, ...);

double dLenVec(int dim, double* vec);
_Complex double cLenVec(int dim, _Complex double* vec);
double dInnVec(int dim, double* vec1, double* vec2);
_Complex double cInnVec(int dim, _Complex double* vec1, _Complex double* vec2);
double** dOutVec(int* dims, double* vec1, double* vec2);
_Complex double** cOutVec(int* dims, _Complex double* vec1, _Complex double* vec2);
double* dStretchVec(int dim, double* vec, double factor);
_Complex double* cStretchVec(int dim, _Complex double* vec, _Complex double factor);
double* dGetZeroVec(int dim);
_Complex double* cGetZeroVec(int dim);
double* dGetOnesVec(int dim);
_Complex double* cGetOnesRVec(int dim);
_Complex double* cGetOnesIVec(int dim);
_Complex double* cGetOnesRIVec(int dim);
_Complex double* getCplxRVec(int dim, double* reVec);
_Complex double* getCplxIVec(int dim, double* ImVec);
_Complex double* getCplxRIVec(int dim, double* reVec, double* imVec);
double* getVecRealPart(int dim, _Complex double* vec);
double* getVecImagPart(int dim, _Complex double* vec);
double* getVecNormPart(int dim, _Complex double* vec);
double* getVecArgPart(int dim, _Complex double* vec);

struct dVecFeature {
    double (*length)(int, double*);
    double (*innerProd)(int, double*, double*);
};

struct cVecFeature {
    _Complex double (*length)(int, _Complex double*);
    _Complex double (*innerProd)(int, _Complex double*, _Complex double*);
};

struct dNewVec {
    double* (*create)(int);
    double* (*sample)(int, _Complex double*);
};

struct cNewVec {
    _Complex double* (*create)(int);
    _Complex double* (*new1)(int, double*);
    _Complex double* (*new2)(int, double*, double*);
};

struct dVecFeature dvf(void);
struct cVecFeature cvf(void);
struct dNewVec dNewV(int mode);
struct cNewVec cNewV(int mode);

double** dTrans(int* dims, double** mat);
_Complex double** cTrans(int* dims, _Complex double** mat);
_Complex double** conjugateMat(int* dims, _Complex double** mat);
_Complex double** dagger(int* dims, _Complex double** mat);
double** dGetZeroMat(int* dims);
_Complex double** cGetZeroMat(int* dims);
double** dGetOnesMat(int* dims);
_Complex double** cGetOnesRMat(int* dims);
_Complex double** cGetOnesIMat(int* dims);
_Complex double** cGetOnesRIMat(int* dims);
double** dGetUniteMat(int dim);
_Complex double** cGetUniteRMat(int dim);
_Complex double** cGetUniteIMat(int dim);
_Complex double** cGetUniteRIMat(int dim);
_Complex double** getCplxRMat(int* dims, double** reMat);
_Complex double** getCplxIMat(int* dims, double** imMat);
_Complex double** getCplxRIMat(int* dims, double** reMat, double** imMat);
double** getMatRealPart(int* dims, _Complex double** mat);
double** getMatImagPart(int* dims, _Complex double** mat);
double** getMatNormPart(int* dims, _Complex double** mat);
double** getMatArgPart(int* dims, _Complex double** mat);
double** dDiagMat(int dim, double* values);
_Complex double** cDiagMat(int dim, _Complex double* values);
double* * dVecCpy(int dim, double* vector);
_Complex double* * cVecCpy(int dim, _Complex double* vector);
double** * dMatCpy(int* dims, double** matrix);
_Complex double** * cMatCpy(int* dims, _Complex double** matrix);

struct dNewMat {
    double** (*create_sm)(int);
    double** (*create_rm)(int*);
    double** (*sample)(int*, _Complex double**);
    double** (*new)(int, double*);
};

struct cNewMat {
    _Complex double** (*create_sm)(int);
    _Complex double** (*create_rm)(int*);
    _Complex double** (*new0)(int*, double**, double**);
    _Complex double** (*new1)(int*, double**);
    _Complex double** (*new2)(int, _Complex double*);
};

struct dNewMat dNewM(int shape, int mode);
struct cNewMat cNewM(int shape, int mode);

void dExchangeLines(double** mat, int* dims, int* locates);
void dExchangeRows(double** mat, int* dims, int* locates);
void dMultipleLine(double** mat, int* dims, int locate, double factor);
void dMultipleRow(double** mat, int* dims, int locate, double factor);
void dDoubledLines(double** mat, int* dims, int* locates, double factor);
void dDoubledRows(double** mat, int* dims, int* locates, double factor);
void cExchangeLines(_Complex double** mat, int* dims, int* locates);
void cExchangeRows(_Complex double** mat, int* dims, int* locates);
void cMultipleLine(_Complex double** mat, int* dims, int locate, _Complex double factor);
void cMultipleRow(_Complex double** mat, int* dims, int locate, _Complex double factor);
void cDoubledLines(_Complex double** mat, int* dims, int* locates, _Complex double factor);
void cDoubledRows(_Complex double** mat, int* dims, int* locates, _Complex double factor);

struct dConvertVec {
    double* (*stretch)(int, double*, double);
};

struct cConvertVec {
    _Complex double* (*stretch)(int, _Complex double*, _Complex double);
};

struct dSwitchMat {
    void (*exc)(double**, int*, int*);
    void (*mul)(double**, int*, int, double);
    void (*dbl)(double**, int*, int*, double);
};

struct cSwitchMat {
    void (*exc)(_Complex double**, int*, int*);
    void (*mul)(_Complex double**, int*, int, _Complex double);
    void (*dbl)(_Complex double**, int*, int*, _Complex double);
};

struct dConvertMat {
    double** (*trans)(int*, double**);
};

struct cConvertMat {
    _Complex double** (*trans)(int*, _Complex double**);
    _Complex double** (*conj)(int*, _Complex double**);
    _Complex double** (*dag)(int*, _Complex double**);
};

struct dConvertVec dCvtV(void);
struct cConvertVec cCvtV(void);
struct dSwitchMat dSwtM(char mode);
struct cSwitchMat cSwtM(char mode);
struct dConvertMat dCvtM(void);
struct cConvertMat cCvtM(void);

void dPrtVec(int dim, double* vec, double format);
void dFprtVec(FILE* fp, int dim, double* vec, double format);
void dPrtMat(int* dims, double** mat, double format);
void dFprtMat(FILE* fp, int* dims, double** mat, double format);
void cPrtVecXY(int dim, _Complex double* vec, double format);
void cFprtVecXY(FILE* fp, int dim, _Complex double* vec, double format);
void cPrtMatXY(int* dims, _Complex double** mat, double format);
void cFprtMatXY(FILE* fp, int* dims, _Complex double** mat, double format);
void cPrtVecRT(int dim, _Complex double* vec, double format);
void cFprtVecRT(FILE* fp, int dim, _Complex double* vec, double format);
void cPrtMatRT(int* dims, _Complex double** mat, double format);
void cFprtMatRT(FILE* fp, int* dims, _Complex double** mat, double format);

struct printArray {
    void (*dv)(int, double*, double);
    void (*fdv)(FILE*, int, double*, double);
    void (*dm)(int*, double**, double);
    void (*fdm)(FILE*, int*, double**, double);
    void (*cv)(int, _Complex double*, double);
    void (*fcv)(FILE*, int, _Complex double*, double);
    void (*cm)(int*, _Complex double**, double);
    void (*fcm)(FILE*, int*, _Complex double**, double);
};

struct printArray prtArr(int form);

double** dMatrixLineSimAlpha(int* dims, double** matrix);
double** dMatrixLineSimBeta(int* dims, double** matrix);
_Complex double** cMatrixLineSimAlpha(int* dims, _Complex double** matrix);
_Complex double** cMatrixLineSimBeta(int* dims, _Complex double** matrix);
double** dMatrixRowSimAlpha(int* dims, double** matrix);
double** dMatrixRowSimBeta(int* dims, double** matrix);
_Complex double** cMatrixRowSimAlpha(int* dims, _Complex double** matrix);
_Complex double** cMatrixRowSimBeta(int* dims, _Complex double** matrix);
double** * dCreateGivensMatrix(int dim, int* locateIndex, double rotateAngle);
_Complex double** * cCreateGivensMatrix(int dim, int* locateIndex, double rotateAngle, double* phases);
void dGivensTransDirect(int dim, double** * matrixPointer, double** givensMat);
void cGivensTransDirect(int dim, _Complex double** * matrixPointer, _Complex double** givensMat);
void dGivensTrans(int dim, double** * matrixPointer, int* locateIndex, double rotateAngle);
void cGivensTrans(int dim, _Complex double** * matrixPointer, int* locateIndex, double rotateAngle, double* phases);
double** * dCreateHouseholderMatrix(int dim, double* vector);
_Complex double** * cCreateHouseholderMatrix(int dim, _Complex double* vector);
double** * dHouseholderReflex(int dim, double* vector, double* direction);
_Complex double** * cHouseholderReflex(int dim, _Complex double* vector, _Complex double* direction);

#endif //PHYSICAL_COMPUTING_PACKAGE_MATRIXOPERATE_H
